home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_054 / ispell / buildhash.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  6KB  |  337 lines

  1. /* -*- Mode: Text -*- */
  2. /*
  3.  * buildhash.c - make a hash table for ispell
  4.  *
  5.  * Pace Willisson, 1983
  6.  */
  7.  
  8. #include <stdio.h>
  9.  
  10. #ifdef unix
  11. #  include <sys/types.h>
  12. #  include <sys/stat.h>
  13. #else
  14. #  ifdef AMIGA
  15. #    include "types.h"
  16. #    include "stat.h"
  17. #  else
  18. #    include <types.h>
  19. #    include <stat.h>
  20. #  endif
  21. #endif
  22.  
  23. #include "ispell.h"
  24.  
  25. #define DICT "dict.191"
  26. #define COUNT "count.191"
  27. #define STATS "stats.191"
  28.  
  29. #define NSTAT 100
  30. struct stat dstat, cstat;
  31.  
  32. int numwords, hashsize;
  33.  
  34. char *malloc();
  35.  
  36. struct dent *hashtbl;
  37.  
  38. main ()
  39. {
  40.     FILE *countf;
  41.     FILE *statf;
  42.     int stats[NSTAT];
  43.     int i;
  44.  
  45.     if (stat (DICT, &dstat) < 0) {
  46.         fprintf (stderr, "No dictionary (%s)\n", DICT);
  47.         exit (1);
  48.     }
  49.  
  50.     if (stat (COUNT, &cstat) < 0 || dstat.st_mtime > cstat.st_mtime)
  51.         newcount ();
  52.  
  53.     if ((countf = fopen (COUNT, "r")) == NULL) {
  54.         fprintf (stderr, "No count file\n");
  55.         exit (1);
  56.     }
  57.     numwords = 0;
  58.     fscanf (countf, "%d", &numwords);
  59.     fclose (countf);
  60.     if (numwords == 0) {
  61.         fprintf (stderr, "Bad count file\n");
  62.         exit (1);
  63.     }
  64.     hashsize = numwords;
  65.     readdict ();
  66.  
  67.     if ((statf = fopen (STATS, "w")) == NULL) {
  68.         fprintf (stderr, "Can't create %s\n", STATS);
  69.         exit (1);
  70.     }
  71.  
  72.     for (i = 0; i < NSTAT; i++)
  73.         stats[i] = 0;
  74.     for (i = 0; i < hashsize; i++) {
  75.         struct dent *dp;
  76.         int j;
  77.         if (hashtbl[i].used == 0) {
  78.             stats[0]++;
  79.         } else {
  80.             for (j = 1, dp = &hashtbl[i]; dp->next != NULL; j++, dp = dp->next)
  81.                 ;
  82.             if (j >= NSTAT)
  83.                 j = NSTAT - 1;
  84.             stats[j]++;
  85.         }
  86.     }
  87.     for (i = 0; i < NSTAT; i++)
  88.         fprintf (statf, "%d: %d\n", i, stats[i]);
  89.     fclose (statf);
  90.  
  91.     filltable ();
  92.  
  93.     output ();
  94. }
  95.  
  96. output ()
  97. {
  98.     FILE *outfile;
  99.     struct hashheader hashheader;
  100.     int strptr, n, i;
  101.  
  102.     if ((outfile = fopen ("ispell.hash", "w")) == NULL) {
  103.         fprintf (stderr, "can't create ispell.hash\n");
  104.         return;
  105.     }
  106.     hashheader.magic = MAGIC;
  107.     hashheader.stringsize = 0;
  108.     hashheader.tblsize = hashsize;
  109.     fwrite (&hashheader, sizeof hashheader, 1, outfile);
  110.     strptr = 0;
  111.     for (i = 0; i < hashsize; i++) {
  112.         n = strlen (hashtbl[i].word) + 1;
  113.         fwrite (hashtbl[i].word, n, 1, outfile);
  114.         hashtbl[i].word = (char *)strptr;
  115.         strptr += n;
  116.     }
  117.     for (i = 0; i < hashsize; i++) {
  118.         if (hashtbl[i].next != 0) {
  119.             int x;
  120.             x = hashtbl[i].next - hashtbl;
  121.             hashtbl[i].next = (struct dent *)x;
  122.         } else {
  123.             hashtbl[i].next = (struct dent *)-1;
  124.         }
  125.     }
  126.     fwrite (hashtbl, sizeof (struct dent), hashsize, outfile);
  127.     hashheader.stringsize = strptr;
  128.     rewind (outfile);
  129.     fwrite (&hashheader, sizeof hashheader, 1, outfile);
  130.     fclose (outfile);
  131. }
  132.  
  133. filltable ()
  134. {
  135.     struct dent *freepointer, *nextword, *dp;
  136.     int i;
  137.  
  138.     for (freepointer = hashtbl; freepointer->used; freepointer++)
  139.         ;
  140.     for (nextword = hashtbl, i = numwords; i != 0; nextword++, i--) {
  141.         if (nextword->used == 0) {
  142.             continue;
  143.         }
  144.         if (nextword->next == NULL) {
  145.             continue;
  146.         }
  147.         if (nextword->next >= hashtbl && nextword->next < hashtbl + hashsize) {
  148.             continue;
  149.         }
  150.         dp = nextword;
  151.         while (dp->next) {
  152.             if (freepointer > hashtbl + hashsize) {
  153.                 fprintf (stderr, "table overflow\n");
  154.                 getchar ();
  155.                 break;
  156.             }
  157.             *freepointer = *(dp->next);
  158.             dp->next = freepointer;
  159.             dp = freepointer;
  160.  
  161.             while (freepointer->used)
  162.                 freepointer++;
  163.         }
  164.     }
  165. }
  166.  
  167.  
  168. readdict ()
  169. {
  170.     struct dent d;
  171.     char lbuf[100];
  172.     FILE *dictf;
  173.     int i;
  174.     int h;
  175.     char *p;
  176.  
  177.     if ((dictf = fopen (DICT, "r")) == NULL) {
  178.         fprintf (stderr, "Can't open dictionary\n");
  179.         exit (1);
  180.     }
  181.  
  182.     hashtbl = (struct dent *) calloc (numwords, sizeof (struct dent));
  183.     if (hashtbl == NULL) {
  184.         fprintf (stderr, "couldn't allocate hash table\n");
  185.         exit (1);
  186.     }
  187.  
  188.     i = 0;
  189.     while (fgets (lbuf, sizeof lbuf, dictf) != NULL) {
  190.         if (i % 1000 == 0) {
  191.             printf ("%d ", i);
  192.             fflush (stdout);
  193.         }
  194.         i++;
  195.  
  196.         p = &lbuf [ strlen (lbuf) - 1 ];
  197.         if (*p == '\n')
  198.             *p = 0;
  199.  
  200.         if (makedent (lbuf, &d) < 0)
  201.             continue;
  202.  
  203.         d.word = malloc (strlen (lbuf) + 1);
  204.         if (d.word == NULL) {
  205.             fprintf (stderr, "couldn't allocate space for word %s\n", lbuf);
  206.             exit (1);
  207.         }
  208.         strcpy (d.word, lbuf);
  209.  
  210.         h = hash (lbuf, strlen (lbuf), hashsize);
  211.  
  212.         if (hashtbl[h].used == 0) {
  213.             hashtbl[h] = d;
  214.  
  215.         } else {
  216.             struct dent *dp;
  217.  
  218.             dp = (struct dent *) malloc (sizeof (struct dent));
  219.             if (dp == NULL) {
  220.                 fprintf (stderr, "couldn't allocate space for collision\n");
  221.                 exit (1);
  222.             }
  223.             *dp = d;
  224.             dp->next = hashtbl[h].next;
  225.             hashtbl[h].next = dp;
  226.         }
  227.     }
  228.     printf ("\n");
  229. }
  230.  
  231. /*
  232.  * fill in the flags in d, and put a null after the word in s
  233.  */
  234.  
  235. makedent (lbuf, d)
  236. char *lbuf;
  237. struct dent *d;
  238. {
  239.     char *p, *index();
  240.  
  241.     d->next = NULL;
  242.     d->used = 1;
  243.     d->v_flag = 0;
  244.     d->n_flag = 0;
  245.     d->x_flag = 0;
  246.     d->h_flag = 0;
  247.     d->y_flag = 0;
  248.     d->g_flag = 0;
  249.     d->j_flag = 0;
  250.     d->d_flag = 0;
  251.     d->t_flag = 0;
  252.     d->r_flag = 0;
  253.     d->z_flag = 0;
  254.     d->s_flag = 0;
  255.     d->p_flag = 0;
  256.     d->m_flag = 0;
  257.  
  258.     p = index (lbuf, '/');
  259.     if (p != NULL)
  260.         *p = 0;
  261.     if (strlen (lbuf) > WORDLEN - 1) {
  262.         printf ("%s: word too big\n");
  263.         return (-1);
  264.     }
  265.  
  266.     if (p == NULL)
  267.         return (0);
  268.  
  269.     p++;
  270.     while (*p != NULL) {
  271.         switch (*p) {
  272.         case 'V': d->v_flag = 1; break;
  273.         case 'N': d->n_flag = 1; break;
  274.         case 'X': d->x_flag = 1; break;
  275.         case 'H': d->h_flag = 1; break;
  276.         case 'Y': d->y_flag = 1; break;
  277.         case 'G': d->g_flag = 1; break;
  278.         case 'J': d->j_flag = 1; break;
  279.         case 'D': d->d_flag = 1; break;
  280.         case 'T': d->t_flag = 1; break;
  281.         case 'R': d->r_flag = 1; break;
  282.         case 'Z': d->z_flag = 1; break;
  283.         case 'S': d->s_flag = 1; break;
  284.         case 'P': d->p_flag = 1; break;
  285.         case 'M': d->m_flag = 1; break;
  286.         case 0:
  287.              fprintf (stderr, "no key word %s\n", lbuf);
  288.             continue;
  289.         default:
  290.             fprintf (stderr, "unknown flag %c word %s\n", 
  291.                     *p, lbuf);
  292.             break;
  293.         }
  294.         p++;
  295.         if (*p != '/' && *p != NULL && *p != '\n') {
  296.             fprintf (stderr, "bad format %s (%c 0%o)\n", 
  297.                     lbuf, *p, *p);
  298.             break;
  299.         }
  300.         if (*p)
  301.             p++;
  302.     
  303.     }
  304.     return (0);
  305. }
  306.  
  307. newcount ()
  308. {
  309.     char buf[200];
  310.     FILE *d;
  311.     int i;
  312.  
  313.     fprintf (stderr, "Counting words in dictionary ...\n");
  314.  
  315.     if ((d = fopen (DICT, "r")) == NULL) {
  316.         fprintf (stderr, "Can't open dictionary\n");
  317.         exit (1);
  318.     }
  319.  
  320.     i = 0;
  321.     while (fgets (buf, sizeof buf, d) != NULL) {
  322.         i++;
  323.         if (i % 1000 == 0) {
  324.             printf ("%d ", i);
  325.             fflush (stdout);
  326.         }
  327.     }
  328.     fclose (d);
  329.     printf ("\n%d words\n", i);
  330.     if ((d = fopen (COUNT, "w")) == NULL) {
  331.         fprintf (stderr, "can't create %s\n", COUNT);
  332.         exit (1);
  333.     }
  334.     fprintf (d, "%d\n", i);
  335.     fclose (d);
  336. }
  337.